package com.br.generateswingview.core;

import java.awt.Component;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.text.DefaultFormatterFactory;
import javax.swing.text.NumberFormatter;

import com.br.dnaklass.core.FamilyTree;
import com.br.generateswingview.annotations.Alias;
import com.br.generateswingview.annotations.Ignore;
import com.br.generateswingview.annotations.MaskedField;

@SuppressWarnings( "rawtypes" )
public class GView {
	public static <T> JDialog getView( final T object ) {
		final Class klass = object.getClass();
		int length = 0;
		final JDialog frame = new JDialog();
		frame.setTitle( klass.getSimpleName() );
		frame.setModal( true );

		JPanel panel = new JPanel( new GridLayout( 0, 2 ) );
		List<Class> parents = FamilyTree.getParents( klass );
		for ( Class c : parents ) {
			length += c.getDeclaredFields().length;
			for ( Field field : c.getDeclaredFields() ) {
				if ( field.getAnnotation( Ignore.class ) == null ) {
					panel.add( createLabel( field ) );
					panel.add( createTextField( field ) );
				}
			}
		}

		initFrame( frame, length );
		JButton btnSave = new JButton( "Salvar" );
		btnSave.addActionListener( new ActionListener() {

			@Override
			public void actionPerformed( ActionEvent arg0 ) {
				List<Class> parents = FamilyTree.getParents( klass );
				for ( Class c : parents ) {
					for ( Field field : c.getDeclaredFields() ) {
						if ( field.getAnnotation( Ignore.class ) == null ) {
							field.setAccessible( true );
							String name = field.getName();
							Component component = GVUtils.getElementByName( frame, name );
							Class type = c = field.getType();
							try {
								if ( component instanceof JComboBox ) {
									field.set( klass.cast( object ), type.cast( ( (JComboBox) component ).getSelectedItem() ) );
								} else if ( component instanceof JTextField ) {
									JTextField textField = ( (JTextField) component );
									if ( type.equals( String.class ) ) {
										field.set( klass.cast( object ), textField.getText() );
									} else if ( type.equals( int.class ) ) {
										field.set( klass.cast( object ), Integer.parseInt( textField.getText() ) );
									} else if ( type.equals( float.class ) ) {
										String text = textField.getText();
										text = text.replaceAll( ",", "" );
										field.set( klass.cast( object ), Float.parseFloat( text ) );
									} else if ( type.equals( double.class ) ) {
										String text = textField.getText();
										text = text.replaceAll( ",", "" );
										field.set( klass.cast( object ), Float.parseFloat( text ) );
										field.set( klass.cast( object ), Double.parseDouble( textField.getText() ) );
									} else if ( type.equals( char.class ) ) {
										field.set( klass.cast( object ), textField.getText().charAt( 0 ) );
									}
								}
							} catch ( IllegalArgumentException e ) {
								e.printStackTrace();
							} catch ( IllegalAccessException e ) {
								e.printStackTrace();
							}
						}
					}
				}
				JOptionPane.showMessageDialog( frame, "Salvo com sucesso!" );
				frame.dispose();
			}

		} );
		panel.add( btnSave );
		panel.add( new JButton( "Limpar" ) );
		frame.getContentPane().add( panel );
		return frame;
	}

	private static void initFrame( JDialog frame, int length ) {
		/*
		 * Toolkit kit = Toolkit.getDefaultToolkit(); Dimension screenSize =
		 * kit.getScreenSize(); frame.setSize( screenSize.width / 4,
		 * screenSize.height / 2 );
		 */
		frame.setResizable( false );
		frame.setSize( 500, 30 * length + 30 );
		frame.setLocationRelativeTo( null );
		frame.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
	}

	private static Component createTextField( Field field ) {
		Component textField;
		if ( field.getAnnotation( MaskedField.class ) != null ) {
			DecimalFormat dFormat = new DecimalFormat( field.getAnnotation( MaskedField.class ).mask() );
			NumberFormatter Formatter = new NumberFormatter( dFormat );
			Formatter.setFormat( dFormat );
			Formatter.setAllowsInvalid( false );
			textField = new JFormattedTextField();
			( (JFormattedTextField) textField ).setFormatterFactory( new DefaultFormatterFactory( Formatter ) );
		} else if ( field.getType().equals( String.class ) ) {
			textField = new JTextField();
		} else if ( !field.getType().isPrimitive() ) {
			textField = new JComboBox();
		} else {
			if ( field.getType().equals( int.class ) ) {
				DecimalFormat dFormat = new DecimalFormat( "###########" );
				NumberFormatter Formatter = new NumberFormatter( dFormat );
				Formatter.setFormat( dFormat );
				Formatter.setAllowsInvalid( false );
				textField = new JFormattedTextField();
				( (JFormattedTextField) textField ).setFormatterFactory( new DefaultFormatterFactory( Formatter ) );
			} else if ( field.getType().equals( float.class ) || field.getType().equals( double.class ) ) {
				DecimalFormat dFormat = new DecimalFormat( "#,###.##" );
				NumberFormatter Formatter = new NumberFormatter( dFormat );
				Formatter.setFormat( dFormat );
				Formatter.setAllowsInvalid( true );
				textField = new JFormattedTextField();
				( (JFormattedTextField) textField ).setFormatterFactory( new DefaultFormatterFactory( Formatter ) );
			} else {
				textField = new JTextField();
			}
		}
		textField.setName( field.getName() );

		return textField;
	}

	private static JLabel createLabel( Field field ) {
		JLabel label = new JLabel();
		label.setName( "L".concat( field.getName() ) );
		if ( field.getAnnotation( Alias.class ) != null ) {
			Alias alias = field.getAnnotation( Alias.class );
			label.setText( alias.value() );
			if ( alias.name() != "" ) {

			}
		} else {
			String name = field.getName();
			String alias = name.substring( 0, 1 ).toUpperCase();
			alias += field.getName().substring( 1, name.length() );
			label.setText( alias );
		}
		return label;
	}
}
